/**
	author: felix fuellgraf <felix.fuellgraf -AT-  gmail.com>

	compile with: g++ pwcrack.cpp -o pw

	run with: ./pw <maximum length for the passwords> [silent]


*/

#include <iostream>
#include <time.h>

using namespace std;

/* ending and starting value of ascii set */
int START = 97;
int BASE = 123 - START;

string getLetter(int val)
{
	if(val==-1) return "";

	/* value+offset, we start always with 0 */
	string out;
	out = START + val;


	return out;
}

int main(int argc, char** argv)
{
	bool silent = false;
	
	if(argc==2 || argc==3)
	{
		/* get input params */
		int max = atoi(argv[1]);
		if(argc==3) if(!strcmp(argv[2],"silent")) silent = true;		

		/* init password space */
		int *password_token = new int[max];
		for(int i=0; i<max; i++)
		{
			password_token[i] = -1;
		}

		/* start time logging */
		long time1 = time(0);
	
		long counter = 0;
		bool endofall = false;

		while(!endofall)
		{
			for(int i=0; i<max; i++)
			{
				/* count */
				password_token[i]++;

				/* if value is under base, next i */
				if(password_token[i]<BASE) break;

				/* if last one equals base, end algorithm */
				else if(password_token[max-1]==BASE) endofall=true;

				/* last choice: actual value is greater than base, reset to zero */
				else 
				{
					password_token[i] =0;
				}
				/* go on with i++ (next number will increase) */
			}
			
			/* based of the values in the array, build letter for every group and output */
			if(!silent) for(int i=0; i<max; i++)cout << getLetter(password_token[i]);
			
			/* build finished, eol */
			if(!silent) cout << endl;

			counter++;
		}

		/* benchmark results */
		int totaltime = time(0)-time1+1;
		cout << endl << "Time total:\t" << totaltime << "\tseconds" << endl;
		cout << "Passwords:\t" << counter << endl;
		cout << "Passwords/sec:\t" << (float)counter/(float)(totaltime) << endl;


	}
	else
	{
		cout << "Please input maximum length. Example: ./crack 4 (Will output every possible password up to four characters)" << endl;
	}	

	return 0;
}
